package com.gurumades.jsonform.client.presenter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import com.gurumades.jsonform.client.JsonFormController;
import com.gurumades.jsonform.client.FormsMessages;
import com.gurumades.jsonform.client.JSONUtils;
import com.gurumades.jsonform.client.forms.FormItemViewIF;
import com.gurumades.jsonform.shared.dispatch.SubmitFormResult;

public class JsonFormPresenter {
	public interface Display {
		public JSONObject getDisplayObject();
		public HashMap<String, JSONObject> getDisplayFields();
		public void setData(JSONValue displayFieldsArray, JSONObject displayObject, String userRole);
		Widget asWidget();
		HashMap<String, FormItemViewIF> getFormItems();
		HasClickHandlers cancelButton();
		HasClickHandlers saveButton();
	}
	
	private FormsMessages MESSAGES = FormsMessages.Util.instance();
	
	private JSONObject displayObject;
	private Display display;
	private JsonFormController appController;
	
	private String formID;
	
	private ArrayList<FormItemError> errors = new ArrayList<FormItemError>();

	private AsyncCallback<Object> submitCallBack;

	private Long buildID;
	 
	public JsonFormPresenter(Display display, JSONObject displayObject, JsonFormController controller, String formID){
		try {
			this.display = display;
			this.displayObject = displayObject;
			appController = controller;
			this.formID = formID;
		} catch (Exception ex) {
			Window.alert("constructor" + ex.getMessage());
		}
	}
	

	private void fetchDisplayFields(){
		JSONObject displayFields = appController.getDisplayFields(formID).isObject();
		
		if (displayFields == null) {
			return;
		}

		if (displayObject == null) {
			displayObject = new JSONObject();
		}
		
		display.setData(displayFields.get("line"), displayObject, null);
	}
	

	public void go(HasWidgets container, final JsonFormController appController) {
		try {			
			this.appController = appController;
			container.add(display.asWidget());
			
			display.cancelButton().addClickHandler(new ClickHandler() {
				
				@Override
				public void onClick(ClickEvent event) {
					appController.cancel();
				}
			});
			
			display.saveButton().addClickHandler(new ClickHandler() {
				
				@Override
				public void onClick(ClickEvent event) {
					appController.flush();
					if (getErrors().size() == 0) {
						appController.submit();
					}
				}
			});
			
			this.fetchDisplayFields();
		} catch (Exception ex) {
			Window.alert("go" + ex.getLocalizedMessage());
		}
	}



	public HashMap<String, JSONValue> flush() {
		HashMap<String, FormItemViewIF> items = display.getFormItems();
		HashMap<String, JSONObject> settings = display.getDisplayFields();
		
		errors.clear();
		
		Set<String> keys = items.keySet();
		
		HashMap<String, JSONValue> result = new HashMap<String, JSONValue>();
		
		for (String string : keys) {
			JSONObject row = settings.get(string);
			FormItemViewIF item = items.get(string);
			
			boolean isRequired = JSONUtils.getBoolean("required", row);
			if (isRequired && item.isValueEmpty()) {
				String error = MESSAGES.required_field_errorl(JSONUtils.getString("name", row));
				item.setError(true, error);
				
				errors.add(new FormItemErrorImpl(error, string));
			}else{
				item.setError(false, null);
				
				if (!item.isValueEmpty()) {
					JSONValue value = item.getValue();
					result.put(string, value);
				}
				
			}
		}
		
		return result;
	}
	
	
	public ArrayList<FormItemError> getErrors() {
		return errors;
	}


	public void setErrors(List<FormItemError> errors2) {
		errors.clear();
		errors.addAll(errors2);
		
		HashMap<String, FormItemViewIF> items = display.getFormItems();
		for (FormItemError formItemError : errors2) {
			FormItemViewIF item = items.get(formItemError.getFieldID());
			item.setError(true, formItemError.getMessage());
		}

	}


	public void setBuildID(Long buildID) {
		this.buildID =  buildID;
	}
	
	
	
}
